﻿using System;
using System.Messaging;
using System.Reflection;
using Patriq.Common;
using log4net;

namespace Patriq.Msmq.Router.Core
{
    public interface IRouterScriptEngineExecutor
    {
        void Init();
        string GetDestQueueByMessage(Message message);
    }

    public class RouterScriptEngineExecutor : IRouterScriptEngineExecutor
    {
        private static readonly ILog Logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
        private readonly IConfigFileWatcher dataScriptFileWatcher;
        private readonly IConfigFileWatcher logicScriptFileWatcher;
        private readonly IScriptEngine scriptEngine;
        private dynamic methodHandler;

        public RouterScriptEngineExecutor(IScriptEngine scriptEngine, IConfigFileWatcher dataScriptFileWatcher, 
            IConfigFileWatcher logicScriptFileWatcher)
        {
            this.scriptEngine = scriptEngine;
            this.dataScriptFileWatcher = dataScriptFileWatcher;
            dataScriptFileWatcher.OnFileChanged += ReloadScript;
            dataScriptFileWatcher.OnError += OnFileConfigError;
            this.logicScriptFileWatcher = logicScriptFileWatcher;
            logicScriptFileWatcher.OnFileChanged += ReloadScript;
            logicScriptFileWatcher.OnError += OnFileConfigError;
        }

        public void Init()
        {
            Logger.Debug("Initializing RouterScriptEngineExecutor.");
            dataScriptFileWatcher.Start();
            logicScriptFileWatcher.Start();
            methodHandler = scriptEngine.GetMethodByName("GetDestQueuePathByMessage");
        }

        private void OnFileConfigError(Exception ex)
        {
            Logger.Error("error in ConfigFileWatcher", ex);
        }

        private void ReloadScript()
        {
            scriptEngine.ReLoadScript();
            methodHandler = scriptEngine.GetMethodByName("GetDestQueuePathByMessage");
        }

        public string GetDestQueueByMessage(Message message)
        {
            return methodHandler(message);
        }
    }
}